/**$Licence:
 *   Use this however/wherever you like, just don't blame me if it breaks anything.
 *
 * Copyright (C) 2008 - 2010 www.java1995.cn . All rights reserved.
 * The webmaster's email:zhuxingsheng@gmail.com
 *
 */
package com.blazemina.mina.handler;

import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.demux.MessageDecoder;

import com.blazemina.Globals;
import com.blazemina.config.BlazeminaConfigManager;
import com.blazemina.config.ConfigInitializeException;
import com.blazemina.config.ServiceAcceptor;
import com.blazemina.container.RequestProcessor;
import com.blazemina.message.Message;
import com.blazemina.mina.Request;
import com.blazemina.mina.Response;
import com.blazemina.mina.Session;
import com.blazemina.mina.SocketRequest;
import com.blazemina.mina.SocketResponse;
import com.blazemina.mina.SocketSession;
import com.blazemina.util.ClassUtils;

import flex.messaging.io.amf.ActionMessage;

/**
 * 消息经过Filter处理，到达最后一站，此类把具体处理业务分发给具体处理类
 * 
 * 消息的处理过程：request->decoder->handler->encode->response
 * 
 * <pre>
 * 1、flash发送{@link ActionMessage}-->后台，后台通过消息解码器{@link MessageDecoder}，把二进制流解析为{@link ActionMessage}
 * 2、使用{@link MessageCodcFilter}处理ActionMessage转换成后台业务消息{@link Message}
 * 3、{@link Message}经过{@link MessageCodcFilter},到达{@link ServerHandler}
 * 4、{@link ServerHandler}通过{@link Message}内容，分发给各个service处理具体业务
 * </pre>
 * 
 * 
 * @author JackChu (xingsheng.zhu@gmail.com)
 * @version 1.0 2010-5-22
 */
public class ServerHandler extends IoHandlerAdapter {

	private RequestHandlerHelper requestHandler;

	public ServerHandler(){
		requestHandler = BlazeminaConfigManager.getManager().getBlazeminaConfig().getIoService().getServiceAcceptor().getRequestHandler();
	}

	public void sessionCreated(IoSession ioSession) throws Exception {
		Session session = getSessionFromIoSession(ioSession);
		if(session == null){
			session = getSession(ioSession);
		}
		requestHandler.notifyCreate(session);
	}

	public void messageReceived(IoSession ioSession, Object msgObj)
			throws Exception {
		Message message = (Message) msgObj;
		RequestProcessor processor = getRequestProcessor(ioSession);
		Session session = getSessionFromIoSession(ioSession);
		
		Request request = getRequestFromSession(session, message);
		if(request == null) {
			request = getRequest(session, message);
		}
		Response response = getResponseFromSession(session);
		if(response == null){
			response = getResponse(session);
		}
		processor.processor(request, response);
	}

	/**
	 * 通过Session取得RequestProcessor，可能为null,但并不会创建
	 * 
	 * @param session
	 * @return
	 */
	protected RequestProcessor getRequestProcessorFromSession(IoSession session) {
		RequestProcessor processor = (RequestProcessor) session
				.getAttribute(com.blazemina.Globals.REQUEST_PROCESSOR_KEY);
		return processor;
	}

	/**
	 * 通过Session取得RequestProcessor,create a new one if necessary
	 * 
	 * @param session
	 * @return
	 * @throws ServletException
	 */
	protected synchronized RequestProcessor getRequestProcessor(
			IoSession session) {
		RequestProcessor processor = this
				.getRequestProcessorFromSession(session);
		if (processor == null) {
			ServiceAcceptor serviceAcceptor = BlazeminaConfigManager.getManager().getBlazeminaConfig().getIoService().getServiceAcceptor();
			try {
				processor = (RequestProcessor) ClassUtils
						.applicationInstance(serviceAcceptor
								.getRequestProcessor());
			} catch (Exception e) {
				throw new ConfigInitializeException(
						"Cannot initialize RequestProcessor of class "
								+ serviceAcceptor
										.getRequestProcessor() + ": " + e);
			}
			session.setAttribute(Globals.REQUEST_PROCESSOR_KEY, processor);
		}
		return (processor);
	}

	protected Request getRequestFromSession(Session ioSession, Message message) {
		Request request = (Request) ioSession.getAttribute(Globals.REQUEST_KEY);
		return request;
	}
	
	/**
	 * get reqeust for the iosession,create a new one if necessary
	 * @param ioSession
	 * @param message
	 * @return
	 */
	protected synchronized Request getRequest(Session session, Message message) {
		Request request = getRequestFromSession(session, message);
		if (request == null) {
			request = new SocketRequest(session, message);
			session.setAttribute(Globals.REQUEST_KEY, request);
		}
		return request;
	}
	
	
	protected Response getResponseFromSession(Session ioSession) {
		Response response = (Response) ioSession.getAttribute(Globals.RESPONSE_KEY);
		return response;
	}
	
	/**
	 * get reqeust for the iosession,create a new one if necessary
	 * @param ioSession
	 * @param message
	 * @return
	 */
	protected synchronized Response getResponse(Session session) {
		Response response = getResponseFromSession(session);
		if (response == null) {
			response = new SocketResponse(session);
			session.setAttribute(Globals.REQUEST_KEY, response);
		}
		return response;
	}

	protected Session getSessionFromIoSession(IoSession ioSession) {
		Session session = (Session) ioSession.getAttribute(Globals.SESSION_KEY);
		return session;
	}
	
	protected synchronized Session getSession(IoSession ioSession) {
		Session session = getSessionFromIoSession(ioSession);
		if (session == null) {
			session = new SocketSession(ioSession);
			ioSession.setAttribute(Globals.SESSION_KEY, session);
		}
		return session;
	}
}
